package com.meiyuetao.myt.pairui.service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.namespace.QName;

import lab.s2jh.core.dao.BaseDao;
import lab.s2jh.core.service.BaseService;
import lab.s2jh.core.util.DateUtils;

import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.rpc.client.RPCServiceClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.meiyuetao.myt.md.service.RegionService;
import com.meiyuetao.myt.pairui.dao.PairuiOrderDao;
import com.meiyuetao.myt.pairui.entity.Actiondata;
import com.meiyuetao.myt.pairui.entity.DeliverySendout;
import com.meiyuetao.myt.pairui.entity.OrderData;
import com.meiyuetao.myt.pairui.entity.PairuiDetailOrderXml;
import com.meiyuetao.myt.pairui.entity.PairuiOrder;
import com.meiyuetao.myt.pairui.entity.PairuiOrderXml;
import com.meiyuetao.myt.sale.dao.BoxOrderDetailDao;
import com.meiyuetao.myt.sale.entity.BoxOrder;
import com.meiyuetao.myt.sale.entity.BoxOrder.BoxOrderStatusEnum;
import com.meiyuetao.myt.sale.entity.BoxOrder.PairuiStatusEnum;
import com.meiyuetao.myt.sale.entity.BoxOrderDetail;
import com.meiyuetao.myt.sale.entity.BoxOrderDetail.BoxOrderDetailStatusEnum;
import com.meiyuetao.myt.sale.service.BoxOrderService;
import com.meiyuetao.util.JaxbUtil;

@Service
@Transactional
public class PairuiOrderService extends BaseService<PairuiOrder, Long> {

    @Value("${pairui.orderSendUrl}")
    private String orderSendUrl;
    @Value("${pairui.password}")
    private String password;
    @Value("${pairui.accountNo}")
    private String accountNo;
    @Autowired
    private PairuiOrderDao pairuiOrderDao;
    @Autowired
    private BoxOrderService boxOrderService;
    @Autowired
    private BoxOrderDetailDao boxOrderDetailDao;
    @Autowired
    private RegionService regionService;
    @Autowired
    private DeliverySendoutService deliverySendoutService;

    @Override
    protected BaseDao<PairuiOrder, Long> getEntityDao() {
        return pairuiOrderDao;
    }

    /**
     * 传订单至派瑞
     * 
     * @param boxOrder
     */
    public String postPoForOut(BoxOrder boxOrder) {
        String objectStr = generateOrderToXml(boxOrder);
        String resultXml = postToPairui("billfromerptowms", objectStr);
        String result = "-1";
        result = getXmlValue("<result>(.*?)</result>", resultXml);
        // 执行失败
        if ("-1".equals(result)) {
            result = getXmlValue("<errmessage>(.*?)</errmessage>", resultXml);
            boxOrder.setPairuiStatus(PairuiStatusEnum.P_2);
            boxOrderService.save(boxOrder);
            return "订单号：" + boxOrder.getOrderSeq() + result;
        }
        // 执行成功
        if ("0".equals(result)) {
            result = getXmlValue("<errmessage>(.*?)</errmessage>", resultXml);
            boxOrder.setPairuiStatus(PairuiStatusEnum.P_1);
            boxOrderService.save(boxOrder);
            return "订单号：" + boxOrder.getOrderSeq() + result;
        }
        return result;
    }

    /**
     * 从派瑞上更新物流信息
     * 
     * @param orderSeqs
     */
    public String billquery(BoxOrder boxOrder) {
        // String objectStr = generateSendFbOrderInfoXml(boxOrder.getOrderSeq());
        String objectStr = generateSendFbOrderInfoXml("100000042");
        String resultXml = postToPairui("billquery", objectStr);
        String result = "1";
        result = getXmlValue("<result>(.*?)</result>", resultXml);
        // 执行失败
        if ("1".equals(result)) {
            result = getXmlValue("<errmessage>(.*?)</errmessage>", resultXml);
            return "订单号：" + boxOrder.getOrderSeq() + result;
        }
        // 执行成功
        if ("0".equals(result)) {
            result = getXmlValue("<errmessage>(.*?)</errmessage>", resultXml);
            result = recordFbPoInfo(result, boxOrder);
            return "订单号：" + boxOrder.getOrderSeq() + result;
        }
        return result;
    }

    /**
     * 派瑞系统订单查询返回物流信息更新
     * 
     * @author harvey
     * @since 2015-11-10
     */
    private String recordFbPoInfo(String resxml, BoxOrder boxOrder) {
        String express = getXmlValue("<express>(.*?)</express>", resxml);
        String deliveryno = getXmlValue("<deliveryno>(.*?)</deliveryno>", resxml);
        String updResInfo = "";
        // 如果快递物流有变化则更新
        if (StringUtils.isNotBlank(express) && !deliveryno.equals(boxOrder.getPriLogisticsNo())) {
            boxOrder.setPriLogisticsNo(deliveryno);
            boxOrder.setPriLogisticsName(express);
            for (BoxOrderDetail boxOrderDetail : boxOrder.getBoxOrderDetails()) {
                boxOrderDetail.setDeliveryFinishTime(new Date());
                boxOrderDetail.setLogisticsNo(deliveryno);
                boxOrderDetail.setLogisticsName(express);
                boxOrderDetail.setOrderDetailStatus(BoxOrderDetailStatusEnum.S50DF);
                boxOrderDetailDao.save(boxOrderDetail);
            }
            boxOrder.setDeliveryFinishTime(new Date());
            boxOrder.setOrderStatus(BoxOrderStatusEnum.S50DF);
            boxOrderService.save(boxOrder);
            updatePairuiDelivery(resxml, boxOrder);
            updResInfo = "物流更新成功！";
        } else {
            updResInfo = "快递信息为空或快递单号与派瑞不一致！请确认";
        }
        return updResInfo;
    }

    private void updatePairuiDelivery(String resxml, BoxOrder boxOrder) {
        String express = getXmlValue("<express>(.*?)</express>", resxml);
        String deliveryno = getXmlValue("<deliveryno>(.*?)</deliveryno>", resxml);
        String state = getXmlValue("<state>(.*?)</state>", resxml);
        String receivetime = getXmlValue("<receivetime>(.*?)</receivetime>", resxml);
        String hltime = getXmlValue("<hltime>(.*?)</hltime>", resxml);
        String pickingtime = getXmlValue("<pickingtime>(.*?)</pickingtime>", resxml);
        String checkingtime = getXmlValue("<checkingtime>(.*?)</checkingtime>", resxml);
        String finishtime = getXmlValue("<finishtime>(.*?)</finishtime>", resxml);
        DeliverySendout deliverySendout = deliverySendoutService.findByBillno(boxOrder.getOrderSeq());
        deliverySendout.setBillno(boxOrder.getOrderSeq());
        deliverySendout.setDeliveryno(deliveryno);
        deliverySendout.setExpress(express);
        deliverySendout.setState(state);
        if (!StringUtils.isEmpty(receivetime)) {
            deliverySendout.setReceivetime(DateUtils.parseDate(receivetime));
        }
        if (!StringUtils.isEmpty(hltime)) {
            deliverySendout.setHltime(DateUtils.parseDate(hltime));
        }
        if (!StringUtils.isEmpty(pickingtime)) {
            deliverySendout.setPickingtime(DateUtils.parseDate(pickingtime));
        }
        if (!StringUtils.isEmpty(checkingtime)) {
            deliverySendout.setCheckingtime(DateUtils.parseDate(checkingtime));
        }
        if (!StringUtils.isEmpty(finishtime)) {
            deliverySendout.setFinishtime(DateUtils.parseDate(finishtime));
        }
        deliverySendoutService.save(deliverySendout);
    }

    /**
     * Post To Pairui
     * 
     * @param methodName
     * @param pwd
     * @param objectStr
     * @return postResult
     */
    private String postToPairui(String methodName, String objectStr) {
        Object result = null;
        RPCServiceClient site;
        try {
            site = new RPCServiceClient();
            Options opts = site.getOptions();
            opts.setTo(new EndpointReference(orderSendUrl));
            opts.setAction("urn:get_Impl");
            opts.setPassword(password);
            QName opAddEntry = new QName("http://ws.apache.org/axis2", methodName);
            Object[] object = new Object[2];
            object[0] = password;
            object[1] = objectStr;
            // 指定getGreeting方法返回值的数据类型的Class对象
            @SuppressWarnings("rawtypes")
            Class[] classes = new Class[] { String.class };
            Object[] response = site.invokeBlocking(opAddEntry, object, classes);
            result = response[0];
        } catch (AxisFault e) {
            e.printStackTrace();
            result = "<result>-1<result><errmessage>连接派瑞接口超时</errmessage>";
        }
        return result.toString();
    }

    /**
     * 派瑞订单XML数据收集
     * 
     * @param boxOrder
     * @return
     * @author harvey
     * @since 2015-11-11
     */
    private String generateOrderToXml(BoxOrder boxOrder) {
        PairuiOrderXml po = new PairuiOrderXml();
        // 单据类型 默认2
        // po.setFbilltype("2");
        // 账套号
        po.setFaccountno(accountNo);
        // 原始订单号
        po.setFerporderbillno(boxOrder.getOrderSeq());
        // 帐套号.订单单号
        po.setFerpbillno(accountNo + "." + boxOrder.getOrderSeq());
        // 客户号
        po.setFcustno(boxOrder.getCustomerProfile().getId().toString());
        // erp仓库号
        // erp仓库号
        // 下单日期
        po.setFbilldate(DateUtils.formatTime(boxOrder.getOrderTime()));
        // 备注
        po.setFremark(boxOrder.getMemo());
        // 收货人
        po.setFconsigneekey(boxOrder.getReceivePerson());
        // 收货人省编码
        po.setFcProvince(regionService.findByName(boxOrder.getDeliveryProvince()));
        // 收货人省名称
        po.setFcProvincename(boxOrder.getDeliveryProvince());
        // 收货人城市编码
        po.setFcCity(boxOrder.getDeliveryCity());
        // 收货人城市名称
        po.setFcCityname(boxOrder.getDeliveryCity());
        // 收货人区/县编码
        po.setFcArea(boxOrder.getDeliveryStreet().substring(0, 2));
        // 收货人区县名称
        po.setFcAreaname(boxOrder.getDeliveryStreet());
        // 收货人地址
        po.setFnotes(boxOrder.getDeliveryAddr());
        // 邮编
        po.setFcZip(boxOrder.getPostCode());
        // 联系人
        po.setFcContact1(boxOrder.getReceivePerson());
        // 联系电话
        po.setFcPhone(boxOrder.getMobilePhone());
        // 海关通过条码
        po.setFhgbarcode(boxOrder.getCustomCode());
        // 订单总金额
        po.setFmawb(boxOrder.getActualPayedAmount());
        // 订单总税款金额 TODO
        po.setFhwab(BigDecimal.ZERO);
        // 报价金额
        po.setFbjamt(BigDecimal.ZERO);
        List<PairuiDetailOrderXml> lstPdos = new ArrayList<PairuiDetailOrderXml>();
        for (BoxOrderDetail boxOrderDetail : boxOrder.getBoxOrderDetails()) {
            PairuiDetailOrderXml pdo = new PairuiDetailOrderXml();
            // pdo.setFicno(accountNo + "." + boxOrderDetail.getFicno()); TODO
            pdo.setFicno(accountNo + "." + "11111111");
            pdo.setFunit("个");
            pdo.setFqty(boxOrderDetail.getQuantity());
            pdo.setFprice(boxOrderDetail.getPrice());
            lstPdos.add(pdo);
        }
        Actiondata ad = new Actiondata();
        OrderData od = new OrderData();
        od.setHead(po);
        od.setDetail(lstPdos);
        ad.setAction("billfromerptowms");
        ad.setData(od);
        return JaxbUtil.convertToXml(ad, "gb2312");
    }

    /**
     * 订单状态及各节点查询
     * 
     * @param orderSeqs
     *            账套号.订单号
     * @return
     */
    private String generateSendFbOrderInfoXml(String orderSeqs) {
        StringBuffer sbBillQueXml = new StringBuffer();
        sbBillQueXml.append("<?xml version=\"1.0\" encoding=\"gb2312\"?>");
        sbBillQueXml.append("<actiondata>");
        sbBillQueXml.append("<action>billquery</action>");
        sbBillQueXml.append("<fbilltype>Delivery</fbilltype>");
        sbBillQueXml.append("<purcode>").append(accountNo).append(".").append(orderSeqs).append("</purcode>");
        sbBillQueXml.append("<data> <head> </head> <detail> </detail> </data>");
        sbBillQueXml.append("</actiondata>");
        return sbBillQueXml.toString();
    }

    private String getXmlValue(String pat, String xml) {
        String back = null;
        Pattern resPat = Pattern.compile(pat);
        Matcher matcher = resPat.matcher(xml);
        while (matcher.find()) {
            back = matcher.group(1);
        }
        return back;
    }
}
